%option noyywrap
%option yylineno
%{
    #define YY_NO_UNPUT
    #define YY_NO_INPUT
    
    #include "parser.h"
    #include <string>
    #include <ostream>
    #include <fstream>
    extern FILE *yyin; 
    extern FILE *yyout;
    extern bool dump_tokens;
     
%}

DECIMAL ([1-9][0-9]*|0)
OCT (0[0-7]+)
HEX (0[xX][0-9A-Fa-f]+)
ID [[:alpha:]_][[:alpha:][:digit:]_]*
DECIMAL_FLOAT ((([0-9]*[.][0-9]*([eE][+-]?[0-9]+)?)|([0-9]+[eE][+-]?[0-9]+))[fLlL]?)
HEXADECIMAL_FLOAT (0[xX](([0-9A-Fa-f]*[.][0-9A-Fa-f]*([pP][+-]?[0-9]+)?)|([0-9A-Fa-f]+[pP][+-]?[0-9]+))[fLlL]?)
EOL (\r\n|\n|\r)
WHITE [\t ]

commentblockbegin \/\*
commentelement .
commentblockend \*\/
%x BLOCKCOMMENT
LINECOMMENT (\/\/[^\n]*)
%%
{commentblockbegin} {BEGIN BLOCKCOMMENT;}
<BLOCKCOMMENT>{commentelement} {}
<BLOCKCOMMENT>{commentblockend} {BEGIN INITIAL;}

"int" {
    return INT;
}
"float" {
    return FLOAT;
}
"void" {
    return VOID;
}
"const" {
    return CONST; 
}
"if" {
    return IF;
}
"else" {
    return ELSE;
}
"while" {
    return WHILE;
}
"break" {
    return BREAK;
}
"continue" {
    return CONTINUE;
}
"return" {
    return RETURN;
}
"=" {
    return ASSIGN;
}
"==" {
    return EQ;
}
"!=" {
    return NEQ;
}
"<" {
    return LESS;
}
"<=" {
    return LESSEQ;
}
">" {
    return GREATER;
}
">=" {
    return GREATEREQ;
}
"+" {
    return ADD;
}
"-" {
    return SUB;
}
"*" {
    return MUL;
}
"/" {
    return DIV;
}
"%" {
    return MOD;
}
"||" {
    return OR;
}
"&&" {
    return AND;
}
"!" {
    return NOT;
}
"," {
    return COMMA;
}
";" {
    return SEMICOLON;
}
"(" {
    yylval.lineNo = yylineno; // for starttime & stoptime
    return LPAREN;
}
")" {
    return RPAREN;
}
"[" {
    return LBRACKET;
}
"]" {
    return RBRACKET; 
}
"{" {
    return LBRACE;
}
"}" {
    return RBRACE;
}
"getint" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    Type* funcType = new FunctionType(TypeSystem::intType, {});//返回类型int，无参数
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);//作用域GLOBAL(0)
    globals->install(yytext, se);
    return ID;
}
"getch" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    Type* funcType = new FunctionType(TypeSystem::intType, {});//返回类型int，无参数
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);//作用域GLOBAL(0)
    globals->install(yytext, se);
    return ID;
}
"getfloat" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    Type* funcType = new FunctionType(TypeSystem::floatType, {});//返回类型int，无参数
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);//作用域GLOBAL(0)
    globals->install(yytext, se);
    return ID;
}
"getarray" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType; 
    Type* arrayType = new IntArrayType();
    ((ArrayType*)arrayType)->addDim(-1);
    paramsType.push_back(arrayType);
    Type* funcType = new FunctionType(TypeSystem::intType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"getfarray" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType; 
    Type* arrayType = new FloatArrayType();
    ((ArrayType*)arrayType)->addDim(-1);
    paramsType.push_back(arrayType);
    Type* funcType = new FunctionType(TypeSystem::intType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"putint" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType; 
    paramsType.push_back(TypeSystem::intType);
    Type* funcType = new FunctionType(TypeSystem::voidType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"putch" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType;
    paramsType.push_back(TypeSystem::intType);
    Type* funcType = new FunctionType(TypeSystem::voidType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"putfloat" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType; 
    paramsType.push_back(TypeSystem::floatType);
    Type* funcType = new FunctionType(TypeSystem::voidType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"putarray" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType; 
    paramsType.push_back(TypeSystem::intType);
    Type* arrayType = new IntArrayType();
    ((ArrayType*)arrayType)->addDim(-1);
    paramsType.push_back(arrayType);
    Type* funcType = new FunctionType(TypeSystem::voidType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"putfarray" {
    char *lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    std::vector<Type*> paramsType;
    paramsType.push_back(TypeSystem::intType);
    Type* arrayType = new FloatArrayType();
    ((ArrayType*)arrayType)->addDim(-1);
    paramsType.push_back(arrayType);
    Type* funcType = new FunctionType(TypeSystem::voidType, paramsType);
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, yytext, 0);
    globals->install(yytext, se);
    return ID;
}
"starttime" {
    char *lexeme = new char[6 + strlen(yytext) + 1];
    char* sysy = (char *)"_sysy_";
    strcpy(lexeme, sysy);
    strcpy(lexeme + 6, yytext);
    yylval.strtype = lexeme;
    Type* funcType = new FunctionType(TypeSystem::voidType, {TypeSystem::intType});
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, lexeme, 0);
    globals->install(lexeme, se);
    return ID;
}
"stoptime" {
    char *lexeme = new char[6 + strlen(yytext) + 1];
    char* sysy = (char*)"_sysy_";
    strcpy(lexeme, sysy);
    strcpy(lexeme + 6, yytext);
    yylval.strtype = lexeme;
    Type* funcType = new FunctionType(TypeSystem::voidType, {TypeSystem::intType});
    SymbolEntry* se = new IdentifierSymbolEntry(funcType, lexeme, 0);
    globals->install(lexeme, se);
    return ID;
}
{DECIMAL} {
    yylval.itype = atoi(yytext);
    return INTEGERCONST;
}
{DECIMAL_FLOAT} {
    yylval.ftype = atof(yytext);
    return FLOATCONST;
}
{HEXADECIMAL_FLOAT} {
    sscanf(yytext, "%f", &yylval.ftype);
    return FLOATCONST;
}
{ID} {
    char* lexeme = new char[strlen(yytext) + 1];
    strcpy(lexeme, yytext);
    yylval.strtype = lexeme;
    return ID;
}
{HEX} {
    char* stop;
    int dec = strtol(yytext, &stop, 16);
    yylval.itype = dec;
    return INTEGERCONST;
}
{OCT} {
    char* stop;
    int dec = strtol(yytext, &stop, 8);
    yylval.itype = dec;
    return INTEGERCONST;
}
<*>{EOL} {
} 
{WHITE} {
}
{LINECOMMENT}

%%

